<template>
  <div class="paper-content" :style="prpopsStyle" style="-moz-user-select: none; user-select: none">
    <div class="header">
      <span class="title">工具栏：</span>
      <span class="tool-icon" @click="changeTool('enlarge')">
        <zoom-in-outlined />
        <span class="text">放大</span>
      </span>
      <div class="line"></div>

      <span class="tool-icon" @click="changeTool('narrow')">
        <zoom-out-outlined />
        <span class="text">缩小</span>
      </span>
      <div class="line"></div>

      <span @click="changeTool('reversal')" class="tool-icon">
        <undo-outlined />
        <span class="text">向左旋转</span>
      </span>
      <div class="line"></div>

      <span @click="changeTool('forwardRotate')" class="tool-icon">
        <redo-outlined />
        <span class="text">向右旋转</span>
      </span>
      <div class="line"></div>

      <span class="tool-icon" @click="restoration(false)">
        <swap-outlined />
        <span class="text">试卷复位</span>
      </span>
      <div class="line" v-if="isShowDownload && imgList.length"></div>
      <span class="tool-icon" @click="changeTool('save')" v-if="isShowDownload && imgList.length">
        <arrow-down-outlined />
        <span class="text">下载图片</span>
      </span>
      <div class="line" v-if="props.hasEventDblclick"></div>
      <span
        class="tool-icon"
        title="用于标记，不做记录"
        v-if="props.hasEventDblclick"
        @click="markFun"
      >
        <ExclamationOutlined />
        <span class="text"> {{ Data.modalmarkInfo.markVisible ? '关闭' : '开启' }}双击标记</span>
      </span>
      <slot name="tool"></slot>
    </div>
    <div class="paper-sidebar">
      <div class="min-img" v-if="imgList.length > 1">
        <div
          class="imgStyle overflow-hidden"
          v-for="(item, index) in imgList"
          :key="item?.id"
          :data-style="recordClick && !item?.clickTimes ? '未审阅' : ''"
          :class="{ borderSele: Data.currentIndex == index }"
          @click="handleChoosePicture(index)"
        >
          <div
            style="background: rgba(0, 0, 0, 0.05)"
            class="absolute top-0 left-0 w-full h-full flex items-center justify-center text-[#999999] text-[12px]"
            v-if="!item.loading"
          >
            <div class="text-center">
              <loading-outlined v-if="!item.loadErroring" />
              <div v-if="!item.loadErroring">加载中···</div>
              <div v-else>图片加载失败</div>
            </div>
          </div>
          <img
            :src="imgUrl + item?.fpurl"
            class="w-full h-full absolute left-0 top-0"
            @error="loadErrorListImg(item)"
            @load="loadListImg(item)"
          />
          <left-list-score :imgInfo="item" :tagsList="tagsList"></left-list-score>
        </div>
      </div>
      <div :class="imgList.length > 1 ? 'w-[calc(100%-150px)]' : 'w-full'">
        <div ref="canvasContRef" class="canvas-container">
          <div
            class="alertText hover:z-100"
            v-if="imgList.length > 1 && showTipBool && props.hasEventDblclick"
          >
            温馨提示：当前试题共有多张图片，请审阅全部图片
            <span class="ml-4 cursor-pointer text-red-600">
              <CloseCircleOutlined @click="closetipFun" />
            </span>
          </div>
          <div v-show="Data.imgIsLoad" ref="canvasWrapRef" class="canvas-wrap" :style="canvasStyle">
            <slot
              name="standardmodule"
              :imgInfo="imgList[Data.currentIndex]"
              :scale="Data.canvasValue.scale"
            ></slot>
            <!-- 用于拖拽内容的截图，不显示 -->
            <drag-step
              ref="stepWrapRef"
              :pyDtkqtId="Data.stepWrapInfo.id"
              :tagsList="tagsList"
              :drag-style="Data.stepWrapInfo.style"
              :isHide="true"
              :imglist="imgList"
              v-show="!!Data.stepWrapInfo.id"
            />
            <!-- 回显 -->
            <drag-step
              :pyDtkqtId="imgList[Data.currentIndex]?.id"
              :tagsList="tagsList"
              :rotate="Data.canvasValue.rotate"
              :scale="Data.canvasValue.scale"
              :currentTopic="currentTopic"
            />
            <!-- 标记 -->
            <drag-mark
              :markList="Data.markList"
              :pyDtkqtId="imgList[Data.currentIndex]?.id"
              :rotate="Data.canvasValue.rotate"
              :scale="Data.canvasValue.scale"
              @removeMarkItem="removeMarkItem"
            />
            <!-- 画布 -->
            <a-dropdown
              :trigger="['contextmenu']"
              :disabled="contextmenuValue !== 'menu' || !props.hasEventDblclick"
            >
              <canvas ref="canvasRef" @drop="drop" @dragover="dragover"></canvas>

              <template #overlay>
                <a-menu @click="handleMenuInClick">
                  <a-menu-item v-for="item in menuList" :key="item.key">{{
                    item.name
                  }}</a-menu-item>
                </a-menu>
              </template>
            </a-dropdown>
          </div>

          <div
            style="background: rgba(0, 0, 0, 0.05)"
            class="absolute top-0 left-0 w-full h-full flex items-center justify-center text-[#999999] text-[30px]"
            v-if="!Data.imgIsLoad"
          >
            <div class="text-center">
              <loading-outlined v-if="!Data.imgErrorLoad" />
              <div v-if="!Data.imgErrorLoad">加载中···</div>
              <div v-else>图片加载失败</div>
            </div>
          </div>

          <div
            v-show="Data?.modalmarkInfo?.markPrpopVisible"
            class="absolute top-0 left-0 z-999"
            :style="Data.modalStyle"
          >
            <div
              class="flex bg-white cursor-pointer p-5px"
              style="box-shadow: 0 0 5px rgb(213 204 204); color: #f00"
            >
              <div @click="markTwoFun('1')" class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <CheckOutlined />
              </div>
              <div @click="markTwoFun('2')" class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <CloseOutlined />
              </div>
              <div @click="markTwoFun('3')" class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <QuestionOutlined />
              </div>
              <div
                @click="markTwoFun('4')"
                class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm"
                title="文本描述"
              >
                <FontColorsOutlined />
              </div>
            </div>
          </div>

          <div class="absolute top-0 right-0 z-999" v-if="Data?.markList?.length">
            <div
              class="opacity-70 bg-white cursor-pointer p-5px"
              style="box-shadow: 0 0 5px rgb(213 204 204); color: #f00"
            >
              <div class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <CheckOutlined />：{{ Data?.markList?.filter(item => item.type === '1')?.length }}
              </div>
              <div class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <CloseOutlined />：{{ Data?.markList?.filter(item => item.type === '2')?.length }}
              </div>
              <div class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <QuestionOutlined />：{{
                  Data?.markList?.filter(item => item.type === '3')?.length
                }}
              </div>
              <div class="px-2 py-1 hover:bg-[rgba(0,0,0,0.1)] rounded-sm">
                <FontColorsOutlined />：{{
                  Data?.markList?.filter(item => item.type === '4')?.length
                }}
              </div>
            </div>
          </div>

          <div
            class="modal-content !w-[250px] !h-[135px] !p-2"
            :style="Data.modalStyle"
            v-show="Data?.modalmarkInfo?.markPrpopInputVisible"
            @click.self="selfFunClick"
          >
            <a-textarea
              v-model:value.trim="Data.modalmarkInfo.markPrpopInputValue"
              placeholder="请设置描述"
              :auto-size="{ minRows: 3, maxRows: 3 }"
              maxlength="50"
              show-count
            />
            <div class="mb-2"></div>
            <a-button
              style="margin: 0 10px 0 40px"
              @click="Data.modalmarkInfo.markPrpopInputVisible = false"
            >
              取消
            </a-button>
            <a-button type="primary" @click="markPushCancel('4')">确定</a-button>
          </div>

          <div
            class="modal-content"
            :style="Data.modalStyle"
            v-show="Data?.currentDbClick?.modalVisible"
            @click.self="selfFunClick"
          >
            <div class="modal-header">
              <div class="topic">
                {{ currentTopic?.tmbh ? `当前题目：${currentTopic.tmbh}` : '请选择题目' }}
                <span class="ml-8 text-[red]">
                  最小得分单位：{{ currentTopic?.pydfgc ?? '--' }}
                </span>
              </div>
            </div>
            <a-row class="mb-2">
              <span class="text-[16px] leading-7 font-semibold">请输入分数：</span>
              <InputNumber
                v-model:value="Data.markValue"
                style="width: 170px"
                ref="inputNumFocus"
                :controls="false"
                :placeholder="`满分${currentTopic?.tmfz}分，可手动输入`"
                :max="currentTopic?.tmfz"
                @pressEnter="tmSubnitFun()"
              />
              <a-button style="margin: 0 10px 0 20px" @click="handelCancel">取消</a-button>
              <a-button type="primary" @click="tmSubnitFun(false)">确定</a-button>
            </a-row>
            <a-row justify="center" @click.self="selfFunClick">
              <template v-if="!Data.isShowCount">
                <template v-for="(item, index) in props.countList" :key="index">
                  <a-button class="count" @click="handleClick(index)">
                    {{ `${item[0]} - ${item[item.length - 1]}` }}
                  </a-button>
                </template>
              </template>
              <template v-else>
                <template v-for="(item, num) in props.countList[countIndex]" :key="num">
                  <a-button class="count" @click.stop="markClick(item)">
                    {{ item }}
                  </a-button>
                </template>
                <div class="w-full text-center pt-2 text-[#777]" @click.self="selfFunClick">
                  温馨提示：点击空白还原分数区间
                </div>
              </template>
            </a-row>
            <div class="w-full mt-4" v-if="!currentTopic?.dfdInfoList?.length">
              <a-form
                ref="setLfForm"
                :model="form"
                :labelCol="{ span: 24 }"
                :wrapperCol="{ span: 24 }"
              >
                <div v-if="Data.markValue === 0" class="flex">
                  <a-form-item
                    label="零分原因"
                    :rules="{
                      required: currentTopic.tmlx != '判断题' && currentTopic.tmlx != '填空题',
                      message: '请选择零分原因',
                      trigger: 'change',
                    }"
                    name="lfCode"
                  >
                    <a-radio-group
                      @keydown.enter="tmSubnitFun()"
                      size="small"
                      v-model:value="form.lfCode"
                      button-style="solid"
                    >
                      <div v-for="item in lfYcList" :key="item.value">
                        <a-radio :value="item.value">
                          {{ item.label }}
                        </a-radio>
                      </div>
                    </a-radio-group>
                  </a-form-item>
                  <a-form-item
                    label="零分备注"
                    name="lfBz"
                    :rules="{
                      required: form.lfCode === 'qt',
                      message: '请输入零分备注',
                      trigger: 'blur',
                    }"
                  >
                    <a-textarea v-model:value="form.lfBz" placeholder="请输入零分备注" />
                  </a-form-item>
                </div>
                <!-- <a-form-item label="评分备注" name="pyBz">
                  <a-textarea v-model:value="form.pyBz" placeholder="请输入评分备注" />
                </a-form-item> -->
              </a-form>
              <div class="text-center mt-4">
                <a-button
                  type="danger"
                  v-if="!questionsInfo?.pyZycIdList"
                  class="mr-4 w-2/5"
                  @click="upAbnorFun"
                >
                  上报异常
                </a-button>
                <a-button
                  type="primary"
                  :disabled="isSubmitDisabled"
                  class="w-2/5"
                  @click="tmSubnitFun"
                  @mouseover="hoverFun"
                  :title="submitTip"
                >
                  提交并评阅下一题
                </a-button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import DragStep from './dragStep.vue'
import dragMark from './dragMark.vue'
import { useWatermark } from '/@/hooks/web/useWatermark'
import LeftListScore from './leftListScore.vue'
import domtoimage from 'dom-to-image'
import { InputNumber } from 'ant-design-vue'
import { useTeacherMarkStore } from '/@/store/modules/teacherMark'
import { useUserStoreWithOut } from '/@/store/modules/user'

import { useRoute } from 'vue-router'
const route = useRoute()

import { pyDtkqtClicFun } from '/@/api/teacher'

import { useGlobSetting } from '/@/hooks/setting'
const { imgUrl } = useGlobSetting()
import JSZip from 'jszip'
import FileSaver from 'file-saver'

import {
  computed,
  onMounted,
  onUnmounted,
  ref,
  nextTick,
  defineProps,
  defineExpose,
  watch,
  reactive,
  h,
} from 'vue'

import { useMessage } from '/@/hooks/web/useMessage'
const { createMessage, createConfirm } = useMessage()
const teacherMarkStore = useTeacherMarkStore()
const userStore = useUserStoreWithOut()

const emit = defineEmits(['menuClick', 'nextTopic', 'upAbnor', 'panelStatus', 'closeTip'])

// 当前题目得分分片

const props = defineProps({
  /**
   * 组件样式
   */
  prpopsStyle: {
    type: Object,
    dafault: () => ({}),
  },
  /**
   * 是否创建双击监听事件
   */
  hasEventDblclick: {
    type: Boolean,
    default: false,
  },
  /**
   * 图片列表
   */
  imgList: {
    type: Array,
    default: () => [],
  },
  /**
   * 题目评分明细
   */
  currentTopic: {
    type: Object,
    defaule: () => ({}),
  },
  /**
   * 得分点列表
   */
  tagsList: {
    type: Array,
    default: () => [],
  },
  /**
   * 打分步进列表
   */
  countList: {
    type: Array,
    dafault: () => [],
  },
  /**
   * 当前选中的得分点
   */
  dfdSelected: {
    type: Object,
    deafult: () => ({}),
  },
  /**
   * 当前抽取的题目
   */
  questionsInfo: {
    type: Object,
    deafult: () => ({
      pyZycId: '',
      stId: '',
      pySzId: '',
    }),
  },
  /**
   * 是否需要记录图片列表点击
   */
  recordClick: {
    type: Boolean,
    defaule: false,
  },
  /**
   * 显示图片下载按钮
   */
  isShowDownload: {
    type: Boolean,
    default: false,
  },
  /**
   * 压缩包名字
   */
  jsZipName: {
    type: String,
    default: '图片压缩包',
  },
  /**
   * 右键功能
   * menu: 开启功能菜单
   * panel: 开启评阅面板
   */
  contextmenuValue: {
    type: String,
    default: 'menu',
  },
  /**
   * 右键菜单列表
   */
  menuList: {
    type: Array,
    default: () => [],
  },
  lfYcList: {
    type: Array,
    default: () => [],
  },
  showTipBool: {
    type: Boolean,
    default: true,
  },
} as any)

const Data = reactive({
  currentIndex: 0,
  imgIsLoad: false,
  imgErrorLoad: false,
  canvasValue: {
    width: 0,
    height: 0,
    left: 0,
    top: 0,
    scale: 1,
    rotate: 0,
    cursor: 'default',
    dafaltScale: 1,
  },
  currentDbClick: {
    x: 0,
    y: 0,
    modalVisible: false,
  },
  markValue: undefined,
  isShowCount: false,
  modalStyle: {
    top: '0px',
    left: '0px',
  },
  stepWrapInfo: {
    // 画布的样式
    id: '',
    style: {},
  },
  modalmarkInfo: {
    markVisible: false,
    markPrpopVisible: false,
    markPrpopInputVisible: false,
    markPrpopInputValue: '',
  },
  markList: [],
} as any)

/**
 *提示标语u关闭按钮

 */

function closetipFun() {
  createConfirm({
    iconType: 'warning',
    title: () => h('span', '温馨提醒'),
    okText: '不再显示标语',
    cancelText: '关闭标语',
    content: () => h('span', '是否关闭提示标语？'),
    onOk: () => {
      emit('closeTip', true)
    },
    onCancel: () => {
      emit('closeTip', false)
    },
  })
}

function selfFunClick() {
  Data.isShowCount = false
}

async function handleChoosePicture(index) {
  if (Data.currentDbClick.modalVisible && typeof Data.markValue === 'number') {
    tmSubnitFun(false)
  }
  nextTick(() => {
    Data.currentIndex = index
  })
}

const canvasWrapRef = ref()
const canvasContRef = ref()
const canvasRef = ref()
const stepWrapRef = ref()

const imgData = ref(null)
const preDrawAry = <any>ref([])

const canvasStyle = computed(() => {
  const { width, height, left, top, scale, rotate, cursor } = Data.canvasValue
  return {
    width: `${width}px`,
    height: `${height}px`,
    left: `${left}px`,
    top: `${top}px`,
    transform: `rotate(${rotate}deg) scale(${scale}) translateZ(0)`,
    cursor: cursor,
  }
})

const countIndex = ref(0)
const handleClick = i => {
  countIndex.value = i
  Data.isShowCount = true
}

watch(
  () => props.countList,
  () => {
    selfFunClick()
  }
)

function loadListImg(e) {
  e.loading = true
}

function loadErrorListImg(e) {
  e.loadErroring = true
}

watch(
  () => [Data.currentIndex, props.imgList],
  () => {
    Data.imgIsLoad = false
    Data.imgErrorLoad = false
    if (props.imgList[Data.currentIndex]) {
      loadImg()
      props.imgList[Data.currentIndex].clickTimes += 1
      // 图片点击问题
      props.recordClick &&
        pyDtkqtClicFun({
          dtkqtId: props.imgList[Data.currentIndex]?.id, //答题卡切图id(同C端dtkqtxx表主键)
          pyZycId: props.questionsInfo?.pyZycId, //评阅资源池的主观题id
          stId: props.questionsInfo?.stId, //试题id
          kmdm: route.query.kmdm, //科目代码
          pySzId: props.questionsInfo?.pySzId,
        })
    } else {
      Data.imgErrorLoad = true
    }
  }
)

const inputNumFocus = ref()

//记录点击事件
let eventTagter: any = {}

// 双击事件
const canvasDblclick = e => {
  eventTagter = {
    type: 'dbmenulclick',
    offsetX: e.offsetX,
    offsetY: e.offsetY,
    clientX: e.clientX,
    clientY: e.clientY,
  }
  if (e.type === 'contextmenu' && props.contextmenuValue === 'menu') return
  // 当前坐标
  Data.currentDbClick.x = e.offsetX
  Data.currentDbClick.y = e.offsetY

  let styBoj = {
    x: 485,
    y: 290,
  }
  Data.modalmarkInfo.markPrpopInputVisible = false
  if (Data.modalmarkInfo.markVisible && e.type === 'dblclick') {
    Data.modalmarkInfo.markPrpopVisible = true
    Data.currentDbClick.modalVisible = false
    styBoj = {
      x: 250,
      y: 150,
    }
  } else {
    Data.currentDbClick.modalVisible = true
    Data.modalmarkInfo.markPrpopVisible = false
    /**没有得分点的情况下回显分数 */
    if (!props.currentTopic?.dfdInfoList?.length && typeof props.currentTopic?.score === 'number') {
      Data.markValue = props.currentTopic?.score
    } else {
      Data.markValue = undefined
      form.value = {
        lfCode: '',
        lfBz: '',
        pyBz: '',
      }
      setTimeout(() => {
        inputNumFocus.value.focus()
      }, 10)
    }
  }

  const wrapContRef = getPosition(canvasContRef.value)
  // 480 290

  Data.modalStyle.left = e.clientX - wrapContRef.left + 'px'
  Data.modalStyle.top = e.clientY - wrapContRef.top + 'px'

  if (e.clientX + styBoj.x - wrapContRef.left > wrapContRef.width) {
    Data.modalStyle.left = wrapContRef.width - styBoj.x + 'px'
  }
  if (e.clientY + styBoj.y - wrapContRef.top > wrapContRef.height) {
    Data.modalStyle.top = wrapContRef.height - styBoj.y + 'px'
  }
}

function handleMenuInClick({ key }) {
  emit('menuClick', key)
}

const markClick = value => {
  Data.markValue = value
  form.value = {
    lfCode: '',
    lfBz: '',
    pyBz: '',
  }
}

/**
 * 验证输入分数
 * @param e
 */
const handelChange = async e => {
  const currentValue = Number(e.target.value)
  if (currentValue % props.currentTopic?.pydfgc != 0) {
    createMessage.error('非法分数')
    return (Data.markValue = undefined)
  } else if (currentValue < 0) {
    createMessage.error('非法分数')
    return (Data.markValue = undefined)
  } else if (currentValue > props.currentTopic?.tmfz) {
    createMessage.error('分数超过题目满分')
    return (Data.markValue = undefined)
  }
}

// 是否校验图片全部点击查看
const isCheckImg = computed(() => {
  let imgLength = props.currentTopic?.dtkqtxxVoList?.length
  let clickTimes = 0
  props.currentTopic.dtkqtxxVoList.forEach(ele => {
    if (ele.clickTimes) clickTimes += 1
  })
  return imgLength != clickTimes
})

/**
 * 提交禁用状态
 */
let isSubmitDisabled = computed(
  () =>
    !!(
      typeof Data.markValue !== 'number' ||
      (props.recordClick && isCheckImg.value && !props.questionsInfo?.pyZycIdList) ||
      (Data.markValue === 0 &&
        (!form.value.lfCode || (form.value.lfCode === 'qt' && !form.value.lfBz)))
    )
)

/**
 * 提交按钮提示信息

 */
let submitTip = ref('')

function hoverFun() {
  if (typeof Data.markValue !== 'number') return (submitTip.value = '请输入分数')

  if (
    Data.markValue === 0 &&
    (!form.value.lfCode || (form.value.lfCode === 'qt' && !form.value.lfBz))
  )
    return (submitTip.value = '请填写零分原因')

  if (props.recordClick && isCheckImg.value && !props.questionsInfo?.pyZycIdList)
    return (submitTip.value = '图片未全部点击')

  return (submitTip.value = '')
}

/**
 * 提交打分
 */
const markSubmit = async () => {
  // 触发校验
  const _event = {
    target: { value: Data.markValue },
  }
  handelChange(_event)
  if (Object.prototype.toString.call(Data.markValue) === '[object Undefined]') return
  if (!props.dfdSelected?.pyDfdId && props.currentTopic?.dfdInfoList?.length)
    return createMessage.error('请选择得分点进行评分')
  if (Number(props.dfdSelected?.dfdScore) < Number(Data.markValue))
    return createMessage.error('分数超过得分点满分')
  let totledfdScole = !props.currentTopic?.dfdInfoList?.length
  teacherMarkStore.setTagsList(totledfdScole ? 'new' : 'update', {
    x: Data.currentDbClick.x,
    y: Data.currentDbClick.y,
    value: Data.markValue,
    stMc: props.currentTopic?.tmbh,
    pyDtkqtId: props.imgList[Data.currentIndex]?.id,
    index: totledfdScole ? 0 : props.dfdSelected?.index,
    pyDfdId: totledfdScole ? 'totleScole' : props.dfdSelected?.pyDfdId,
    dfdId: totledfdScole ? '' : props.dfdSelected?.dfdId,
    pyDfdAutoId: totledfdScole ? '' : props.dfdSelected?.pyDfdAutoId,
  })

  handelCancel()
}

const handelCancel = () => {
  Data.currentDbClick.modalVisible = false
}

onMounted(() => {
  changeTool('drag')
  canvasWrapRef.value.addEventListener('mousewheel', e => {
    let z = e.deltaY > 0 ? -0.1 : 0.1
    changeTool(z > 0 ? 'enlarge' : 'narrow')
  })
})

onUnmounted(() => {
  canvasRef.value?.removeEventListener('dblclick', canvasDblclick)
  canvasRef.value?.removeEventListener('contextmenu', canvasDblclick)
  handelCancel()
})

// 加载图片
const loadImg = () => {
  const img = new Image()
  // 图片加载成功
  img.src = (imgUrl + props.imgList[Data.currentIndex]?.fpurl) as any

  img.onload = () => {
    handelCancel()
    const { width, height } = img
    const oWidth = canvasContRef.value.offsetWidth
    const oHeight = canvasContRef.value.offsetHeight
    Data.canvasValue.width = width
    Data.canvasValue.height = height
    Data.canvasValue.scale = Data.canvasValue.dafaltScale =
      Number((oHeight / height >= oWidth / width ? oWidth / width : oHeight / height).toFixed(1)) *
      0.8

    Data.stepWrapInfo.style = {
      width: width + 'px',
      height: height + 'px',
      background: `url(${img.src}) no-repeat top left/100% 100%`,
    }

    canvasRef.value.width = width - 2
    canvasRef.value.height = height - 2

    Data.imgIsLoad = true
    canvasRef.value.style.backgroundImage = `url(${img.src}?id=${new Date().getTime()})`
    canvasRef.value.style.backgroundSize = '100% 100%'
    canvasCenter()
    nextTick(() => {
      if (props.hasEventDblclick) {
        canvasRef.value.addEventListener('dblclick', canvasDblclick)
        canvasRef.value?.addEventListener('contextmenu', canvasDblclick)
      }
      updateWatermark()
    })
  }
  // 图片加载失败
  img.onerror = () => {
    createMessage.error('图片加载失败')
    Data.canvasValue.width = 0
    Data.canvasValue.height = 0
  }
}

// 切换工具
const changeTool = (name: any) => {
  // 清除拖拽的按下事件
  const wrapRef = canvasWrapRef.value
  wrapRef.onmousedown = null
  const canvas = canvasRef.value
  const ctx = canvas.getContext('2d')
  switch (name) {
    case 'drag':
      dragCanvas()
      break
    case 'draw':
      drawPaint(canvas, ctx)
      break
    case 'eraser':
      eraser(canvas, ctx)
      break
    case 'revoke':
      revoke(canvas, ctx)
      break
    case 'clear':
      clearCanvas(canvas, ctx)
      break
    case 'save':
      saveCanvas().then((imgeList: any[]) => {
        let zip = new JSZip()
        /**
         * 创建文件夹
         */
        let imgs: any = zip.folder(props.jsZipName as string) || []
        for (let k = 0; k < imgeList.length; k++) {
          imgs?.file(`图片${Number(k) + 1}.jpg`, imgeList[k], { binary: true })
        }
        zip.generateAsync({ type: 'blob' }).then(function (content) {
          FileSaver.saveAs(content, `${props.jsZipName || (Math.random() * 100).toFixed(0)}.zip`)
        })
      })
      break
    case 'forwardRotate':
      Data.canvasValue.rotate += 90
      break
    case 'reversal':
      Data.canvasValue.rotate -= 90
      break
    case 'enlarge':
      Data.canvasValue.scale += 0.05
      break
    case 'narrow':
      Data.canvasValue.scale > 0.1 && (Data.canvasValue.scale -= 0.05)
      break
    default:
      break
  }
  dragCanvas()
}

// 拖拽画布
function dragCanvas() {
  // 清除上次监听的事件
  const wrapRef = canvasWrapRef.value

  let isDown = false

  wrapRef.onmousedown = e => {
    isDown = true
    Data.canvasValue.cursor = 'move'
    // 算出鼠标相对元素的位置
    const disX = e.clientX - wrapRef.offsetLeft
    const disY = e.clientY - wrapRef.offsetTop

    document.onmousemove = e => {
      if (!isDown) return

      const wrapContRef = getPosition(canvasContRef.value)
      // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
      let left = e.clientX - disX
      let top = e.clientY - disY
      if (e.clientX > wrapContRef.left && e.clientX < wrapContRef.left + wrapContRef.width) {
        Data.canvasValue.left = left
      }
      if (e.clientY > wrapContRef.top && e.clientY < wrapContRef.top + wrapContRef.height) {
        Data.canvasValue.top = top
      }
    }

    document.onmouseup = () => {
      isDown = false
      document.onmousemove = null
      Data.canvasValue.cursor = 'default'
    }
  }
}

// 画笔
const drawPaint = (canvas, ctx) => {
  canvas.onmousedown = e => {
    Data.canvasValue.cursor = 'crosshair'
    imgData.value = ctx.getImageData(0, 0, canvas.width, canvas.height)
    preDrawAry.value.push(imgData.value)
    ctx.beginPath()
    ctx.lineWidth = 2
    ctx.strokeStyle = 'red'
    ctx.moveTo(e.offsetX, e.offsetY)

    canvas.onmousemove = e => {
      ctx.lineTo(e.offsetX, e.offsetY)
      ctx.stroke()
    }
  }

  // 鼠标抬起取消鼠标移动的事件
  document.onmouseup = (e: MouseEvent) => {
    canvas.onmousemove = null
    ctx.closePath()
    Data.canvasValue.cursor = 'default'
  }

  // 鼠标移出画布时 移动事件取消
  document.onmouseout = (e: MouseEvent) => {
    document.onmousemove = null
    ctx.closePath()
  }
}

// 橡皮擦
const eraser = (canvas, ctx, r = 10) => {
  canvas.onmousedown = e => {
    imgData.value = ctx.getImageData(0, 0, canvas.width, canvas.height)
    preDrawAry.value.push(imgData.value)
    let x1 = e.offsetX
    let y1 = e.offsetY

    // 鼠标第一次点下的时候擦除一个圆形区域，同时记录第一个坐标点
    ctx.save()
    ctx.beginPath()
    ctx.arc(x1, y1, r, 0, 2 * Math.PI)
    ctx.clip()
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    ctx.restore()

    canvas.onmousemove = e => {
      const x2 = e.offsetX
      const y2 = e.offsetY
      // 获取两个点之间的剪辑区域四个端点
      const asin = r * Math.sin(Math.atan((y2 - y1) / (x2 - x1)))
      const acos = r * Math.cos(Math.atan((y2 - y1) / (x2 - x1)))

      // 保证线条的连贯，所以在矩形一端画圆
      ctx.save()
      ctx.beginPath()
      ctx.arc(x2, y2, r, 0, 2 * Math.PI)
      ctx.clip()
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.restore()

      // 清除矩形剪辑区域里的像素
      ctx.save()
      ctx.beginPath()
      ctx.moveTo(x1 + asin, y1 - acos)
      ctx.lineTo(x2 + asin, y2 - acos)
      ctx.lineTo(x2 - asin, y2 + acos)
      ctx.lineTo(x1 - asin, y1 + acos)
      ctx.closePath()
      ctx.clip()
      ctx.clearRect(0, 0, canvas.width, canvas.height)
      ctx.restore()

      // 记录最后坐标
      x1 = x2
      y1 = y2
    }
  }

  // 鼠标抬起取消鼠标移动的事件
  document.onmouseup = (e: MouseEvent) => {
    canvas.onmousemove = null
  }

  // 鼠标移出画布时 移动事件取消
  canvas.onmouseout = (e: MouseEvent) => {
    canvas.onmousemove = null
  }
}

// 撤销
const revoke = (canvas, ctx) => {
  if (preDrawAry.value.length > 0) {
    const popData = preDrawAry.value.pop()
    ctx.putImageData(popData, 0, 0)
  } else {
    clearCanvas(canvas, ctx)
  }
}

// 清空画布
const clearCanvas = (canvas, ctx) => {
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}

// 保存
function saveCanvas(): Promise<Blob[]> {
  return new Promise(async (resolve, reject) => {
    try {
      let imgInList: Blob[] = []
      for (let i = 0; i < props.imgList.length; i++) {
        let ele = props.imgList[i]
        Data.stepWrapInfo.id = ele?.id
        let imgBlob: Blob = await canvasToImg(ele)
        imgInList.push(imgBlob)
      }
      Data.stepWrapInfo.id = false
      resolve(imgInList)
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * 生成图片Blob
 * @param
 */
const canvasToImg = (ele: any): Promise<Blob> => {
  return new Promise((resolve, reject) => {
    try {
      console.log(ele?.tpObj, 'tpObj')
      const img = new Image()
      img.src = imgUrl + (ele?.tpObj?.tpurl || ele?.fpurl)
      img.crossOrigin = 'Anonymous'
      img.onload = async () => {
        const { width, height } = img
        //ymlx 页面类型 1 正面  2 反面
        //zzfx 纸张方向 1 向上  2 向下
        if (ele?.tpObj) {
          Data.stepWrapInfo.style = {
            width: height + 'px',
            height: width + 'px',
          }
        } else {
          Data.stepWrapInfo.style = {
            width: width + 'px',
            height: height + 'px',
          }
        }

        updateWatermark()
        const dataUrl: string = await domtoimage.toJpeg(stepWrapRef.value?.$el, { quality: 0.7 })
        var binaryString = window.atob(dataUrl.split(',')[1])
        var length = binaryString.length
        var binaryArray = new Uint8Array(length)
        for (var i = 0; i < length; i++) binaryArray[i] = binaryString.charCodeAt(i)
        resolve(
          new Blob([binaryArray], {
            type: 'image/jpeg',
          })
        )
      }
      img.onerror = () => {
        reject(new Error('图片加载失败'))
      }
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * 图片加水印
 */
let waterStrMark
function updateWatermark() {
  if (!waterStrMark) {
    waterStrMark = useWatermark(stepWrapRef.value?.$el)
  }
  waterStrMark.setWatermark(userStore.getUserInfo?.account + '')
}

// 获取dom元素在页面中的位置与大小
const getPosition = target => {
  const width = target.offsetWidth
  const height = target.offsetHeight
  let left = 0
  let top = 0
  do {
    left += target.offsetLeft || 0
    top += target.offsetTop || 0
    target = target.offsetParent
  } while (target)
  return { width, height, left, top }
}

// canvas居中显示
const canvasCenter = () => {
  const wrap = getPosition(canvasContRef.value)
  Data.canvasValue.left = (wrap.width - canvasRef.value.width) / 2
  Data.canvasValue.top = (wrap.height - canvasRef.value.height) / 2
}

// 接受拖拽事件
const drop = async e => {
  let { value } = JSON.parse(e.dataTransfer.getData('data'))
  if (!props.dfdSelected?.pyDfdId && props.currentTopic?.dfdInfoList?.length)
    return createMessage.error('请选择得分点进行评分')
  if (Number(props.dfdSelected?.dfdScore) < value) return createMessage.error('分数超过得分点满分')
  let totledfdScole = !props.currentTopic?.dfdInfoList?.length
  teacherMarkStore.setTagsList(totledfdScole ? 'new' : 'update', {
    x: e.offsetX,
    y: e.offsetY,
    value: value,
    stMc: props.currentTopic?.tmbh,
    pyDtkqtId: props.imgList[Data.currentIndex]?.id,
    index: totledfdScole ? 0 : props.dfdSelected?.index,
    pyDfdId: totledfdScole ? 'totleScole' : props.dfdSelected?.pyDfdId,
    dfdId: totledfdScole ? '' : props.dfdSelected?.dfdId,
    pyDfdAutoId: totledfdScole ? '' : props.dfdSelected?.pyDfdAutoId,
  })
}

const dragover = e => {
  // 取消默认动作是为了drop事件可以触发
  e.preventDefault()
}

// 复位还原
const restoration = (e: boolean = true) => {
  Data.canvasValue.scale = Data.canvasValue.dafaltScale
  Data.canvasValue.rotate = 0

  canvasCenter()
  if (e) {
    handleChoosePicture(0)
    Data.markList = []
    Data.modalmarkInfo.markVisible = false
  } else {
  }
}

/**
 * 监听弹窗开启
 */
watch(
  () => Data.currentDbClick.modalVisible,
  nval => {
    emit('panelStatus', nval)
  }
)

const setLfForm = ref()

const form = ref({
  lfCode: '',
  lfBz: '',
  pyBz: '',
})

/**上报异常 */
function upAbnorFun() {
  handelCancel()
  emit('upAbnor')
}

/**
 * 提交并评阅下一题
 */
async function tmSubnitFun(e: boolean = true) {
  if (e) await setLfForm.value?.validate()
  markSubmit()
  nextTick(() => {
    if (
      !Data.currentDbClick.modalVisible &&
      (!props.currentTopic?.dfdInfoList?.length ||
        props.currentTopic?.dfdInfoList?.length == props.tagsList.length)
    ) {
      emit('nextTopic', form.value || {}, e)
    }
  })
}

/**
 * 开启何关闭双击添加标记功能
 */
function markFun() {
  Data.modalmarkInfo.markVisible = !Data.modalmarkInfo.markVisible
}

function markTwoFun(type) {
  Data.modalmarkInfo.markPrpopVisible = false
  if (type !== '4') markPushCancel(type)
  else {
    Data.modalmarkInfo.markPrpopInputVisible = true
    Data.modalmarkInfo.markPrpopInputValue = ''
  }
}

function markPushCancel(type) {
  if (type === '4') {
    Data.modalmarkInfo.markPrpopInputVisible = false
  }

  Data.markList.push({
    pyDfdId: +new Date().getTime(),
    pyDtkqtId: props.imgList[Data.currentIndex]?.id,
    x: Data.currentDbClick.x,
    y: Data.currentDbClick.y,
    value: type === '4' ? Data.modalmarkInfo.markPrpopInputValue : undefined,
    type,
  })
}

function removeMarkItem(pyDfdId) {
  Data.markList = Data.markList.filter(item => item.pyDfdId !== pyDfdId)
}

defineExpose({
  changeTool,
  restoration,
  showPanel: () => {
    /**
     * 打分面板显示
     */
    canvasDblclick(eventTagter)
  },
})
</script>

<style scoped lang="less">
.paper-content {
  background-color: #fff;
  margin-right: 15px;

  .text {
    margin-left: 5px;
  }

  .header {
    width: 100%;
    height: 50px;
    display: flex;
    align-items: center;
    padding-left: 20px;
    border-bottom: 2px solid #ddd;

    .title {
      font-size: 16px;
      font-weight: 700;
      margin-right: 20px;
    }

    .line {
      height: 20%;
      width: 1px;
      margin: 0 20px;
      background: #dddada;
    }
    .tool-icon {
      display: flex;
      align-items: center;
      cursor: pointer;
    }
  }

  .paper-sidebar {
    height: calc(100% - 50px);
    overflow-x: hidden;
    display: flex;

    .min-img {
      height: 100%;
      width: 150px;
      padding: 12px;
      border-right: 1px solid #ccc;
      overflow-y: auto;
      font-size: 0;

      .imgStyle {
        margin-bottom: 10px;
        width: 100%;
        height: 70px;
        border: 1px solid #666;
        cursor: pointer;
        border-radius: 5px;
        position: relative;
        background-size: 100% 100%;
        &::after {
          content: attr(data-style);
          position: absolute;
          left: 5px;
          line-height: 0px;
          display: block;
          top: 15px;
          color: red;
          font-weight: 600;
          font-size: 15px;
        }

        &:last-child {
          margin: 0;
        }
      }

      .borderSele {
        border: 2px solid red;
      }
    }

    .canvas-container {
      width: 100%;
      height: 100%;
      position: relative;
      box-sizing: border-box;
      overflow: hidden;
      .canvas-wrap {
        border: #dbdbdb 1px dashed;
        position: relative;
        transition: transform 0.3s;
        left: 0;
        top: 0;
      }

      .alertText {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        top: 5px;
        color: #666;
        font-size: 14px;
        background-color: #fffbe6;
        border: 1px solid #ffe58f;
        padding: 10px 20px;
        border-radius: 5px;
        white-space: nowrap;
      }
    }
  }
}

.modal-content {
  width: 480px;
  height: 290px;
  padding: 20px;
  box-sizing: border-box;
  position: absolute;
  top: 0;
  left: 0;
  background-color: #efefef;
  opacity: 0.85;
  z-index: 999;
  overflow-x: auto;

  .modal-header {
    .title {
      font-size: 20px;
      font-weight: 700;
      text-align: center;
    }

    .topic {
      font-size: 18px;
      font-weight: 700;
      display: inline-block;
      white-space: nowrap;
      width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
}

.count {
  font-size: 18px;
  font-weight: 700;
  margin: 5px;
  line-height: 18px;
}

.modal-title {
  font-size: 18px;
  color: red;
}
</style>
